package com.sayice.robotconflict.game.handler;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.jwt.JWT;
import com.alibaba.fastjson2.JSON;
import com.sayice.robotconflict.config.JWTConfig;
import com.sayice.robotconflict.game.Game;
import com.sayice.robotconflict.game.msg.Message;
import com.sayice.robotconflict.game.msg.data.send.LoginInfo;
import com.sayice.robotconflict.game.object.Player;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;

import java.util.Base64;

/**
 * 游戏大厅连接处理器
 *
 * @author shubing
 */
@Slf4j
public class ConnectHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        Message message = JSON.parseObject((String) msg, Message.class);
        if ("connect".equals(message.getType())) {
            String encryptedStr = (String) message.getData();
            boolean logind = false;
            String id = null;
            if (encryptedStr != null) {
                try {
                    byte[] encryptedBytes = Base64.getUrlDecoder().decode(encryptedStr);
                    String token = SecureUtil.aes(JWTConfig.TOKEN_SECRET).decryptStr(encryptedBytes);
                    JWT jwt = JWT.of(token);
                    if (jwt.setKey(JWTConfig.SIGN_SECRET).validate(0)) {
                        logind = true;
                        id = (String) jwt.getPayload("id");
                    }
                } catch (Exception e) {
                    log.debug("ConnectHandler 登录校验不通过", e);
                }
            }
            if (logind) {
                Player player;
                // 若为临时退出或者已经在线则恢复状态
                if ((player = Game.TEMP_QUIT_PLAYER_MAP.remove(id)) != null || (player = Game.PLAYER_GROUP.removeById(id)) != null) {
                    ctx.channel().writeAndFlush(new Message("action", "enterHall", new LoginInfo(id)).toJson());
                    player.restoreState(ctx.channel());
                } else {
                    player = new Player(id, ctx.channel());
                    ctx.channel().writeAndFlush(new Message("action", "enterHall", new LoginInfo(id)).toJson());
                }
                Game.PLAYER_GROUP.add(player);
            } else {
                ctx.channel().writeAndFlush(new Message("action", "connectFailed", "未登录").toJson());
                ctx.channel().close();
            }
        } else {
            Player player = Game.PLAYER_GROUP.find(ctx.channel().id());
            if (player == null) {
                ctx.channel().close();
                return;
            }
            ctx.fireChannelRead(new Object[]{player, message});
        }
    }
    
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        // 心跳检测
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                log.debug("客户端" + ctx.channel().remoteAddress() + "超时无请求，关闭该channel");
                ctx.channel().close();
            } else if (event.state() == IdleState.WRITER_IDLE) {
                ctx.channel().writeAndFlush(new Message("heartbeat", null, null).toJson());
            }
        } else {
            ctx.fireUserEventTriggered(evt);
        }
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("NettyHandler Exception from " + ctx.channel().remoteAddress(), cause);
        ctx.channel().close();
    }
}
